with currency;
with ada.text_io;
with ada.sequential_io;

package body bank_account is

    package t_io renames ada.text_io;
    package acc_io is new ada.sequential_io (account);

    initialized : boolean := false;
    accounts : accountArray;
    accountSelected : Boolean;
    numAccounts : natural;
    currentAccount : Integer;
    nextID : Integer;
    dataFile : acc_io.file_type;
    dataFileName : constant string := "accounts.dat";
    backupDataFileName : constant string := "accounts_backup.dat";

    procedure initialize is
    begin
	nextID := 0;
	numAccounts := 0;
	begin
	    acc_io.open(dataFile, acc_io.in_file, dataFileName);
	    loop
		exit when acc_io.end_of_file(dataFile) or NumAccounts = maxAccounts;
		numAccounts := numAccounts + 1;
		acc_io.read(dataFile, accounts(numAccounts));
	    end loop;
	exception
	    when acc_io.name_error =>
		acc_io.create(dataFile, acc_io.in_file, dataFileName);	
	end;
	acc_io.close(dataFile);
	currentAccount := -1;
	accountSelected := false;
	initialized := true;
    end initialize;

    function selectAccount (ID : Integer) return boolean is
    begin
	if initialized = false then
	    initialize;
	end if;
	for i in 1..numAccounts loop
	    if accounts(i).ID = ID then
		currentAccount := i;
		accountSelected := true;
		return true;
	    end if;
	end loop;
	deselectAccount;
	return false;
    end selectAccount;

   procedure deselectAccount is
   begin
	if initialized = false then
	    initialize;
	end if;
	currentAccount := -1;
	accountSelected := false;
    end deselectAccount;

    function createAccount ( ID : Integer ) return Boolean is
	newAcc : account;
    begin
	if initialized = false then
	    initialize;
	end if;
	
	if selectAccount( ID ) = true then
	    return false;
	end if;

	newAcc.ID := ID;
	newAcc.balance := currency.float_to_dollar(0.0);
	newAcc.is_null := false;
	acc_io.open(dataFile, acc_io.append_file, dataFileName);
	acc_io.write(dataFile, newAcc);
	acc_io.close(dataFile);
	numAccounts := numAccounts + 1;
	accounts(numAccounts) := newAcc;
	return true;
    end createAccount;

    function deleteAccount ( ID : Integer ) return Boolean is
	found : Boolean;
    begin
	if initialized = false then
	    initialize;
	end if;
	save(backupDataFileName);
	
	for i in 1..numAccounts loop
	    if accounts(i).ID = ID then
		accounts(i) := accounts(numAccounts);
		numAccounts := numAccounts - 1;
		found := true;
	    end if;
	end loop;

	if found = false then
	    return false;
	end if;

	begin
	    acc_io.open(dataFile, acc_io.in_file, dataFileName);
	    acc_io.delete(dataFile);
	exception
	    when acc_io.name_error => null;
	end;

	acc_io.create(dataFile, acc_io.in_file, dataFileName);
	for i in 1..numAccounts loop
	    acc_io.write(dataFile, accounts(i));
	end loop;
	acc_io.close(dataFile);

	if accounts(currentAccount).ID = ID then
	    deselectAccount;
	end if;
	return true;
    end deleteAccount;

    function deposit ( amount : currency.dollar) return currency.dollar is
    begin
	if initialized = false then
	    initialize;
	end if;
	if accountSelected = false then
	    raise no_account_selected;
	end if;
	accounts(currentAccount).balance := currency.add( accounts(currentAccount).balance, amount);
	save(dataFileName);
	return accounts(currentAccount).balance;
    end deposit;

    function withdraw ( amount : currency.dollar ) return currency.dollar is
    begin
	if accountSelected = false then
	    raise no_account_selected;
	end if;
	accounts(currentAccount).balance := currency.subtract ( accounts(currentAccount).balance, amount );
	save(dataFileName);
	return accounts(currentAccount).balance;
    end withdraw;

    function getBalance return currency.dollar is
    begin
	if accountSelected = false then
	    raise no_account_selected;
	end if;
	return accounts(currentAccount).balance;
    end getBalance;

    procedure save ( fileName : String ) is 
	saveFile : acc_io.file_type;
    begin
	begin
	    acc_io.open(saveFile, acc_io.in_file, fileName);
	    acc_io.delete(saveFile);
	exception
	    when acc_io.name_error =>
		null;
	end;
	acc_io.create(saveFile, acc_io.out_file, fileName);
	for i in 1..numAccounts loop
	    acc_io.write(saveFile, accounts(i));
	end loop;
	acc_io.close(saveFile);
    end save;
	


end bank_account;
